package com.flyme.module.base.provider.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.flyme.common.core.exception.OpenMessageException;
import com.flyme.common.core.model.ResultBody;
import com.flyme.common.core.utils.RandomValueUtils;
import com.flyme.core.base.supper.service.impl.BaseServiceImpl;
import com.flyme.module.base.client.constants.BaseConstants;
import com.flyme.module.base.client.dto.SysAppDto;
import com.flyme.module.base.client.entity.SystemApp;
import com.flyme.module.base.provider.mapper.SysAppMapper;
import com.flyme.module.base.provider.service.SysApiService;
import com.flyme.module.base.provider.service.SysAppService;
import com.flyme.module.base.provider.service.SysAuthorizeService;
import com.flyme.module.base.provider.service.feign.ClientDetailsRemoteServiceClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.Date;
import java.util.List;

/**
 * @author: zyf
 * @date: 2018/11/12 16:26
 * @description:
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class SysAppServiceImpl extends BaseServiceImpl<SysAppMapper, SystemApp> implements SysAppService {

    @Autowired
    private SysAppMapper appMapper;
    @Autowired
    private ClientDetailsRemoteServiceClient clientDetailsRemoteServiceClient;

    @Autowired
    private SysApiService apiService;
    @Autowired
    private SysAuthorizeService grantAccessService;


    /**
     * 获取app和应用信息
     *
     * @param appId
     * @return
     */
    @Override
    public SysAppDto getAppWithClientInfo(String appId) {
        SystemApp appInfo = getById(appId);
        if (appInfo == null) {
            return null;
        }
        SysAppDto appDto = new SysAppDto();
        BeanUtils.copyProperties(appInfo, appDto);
        try {
            appDto.setClientInfo(clientDetailsRemoteServiceClient.getClient(appInfo.getId()).getData());
        } catch (Exception e) {
            log.error("clientDetailsRemoteServiceClient.getClient error:{}", e.getMessage());
        }
        return appDto;
    }

    /**
     * 添加应用
     *
     * @param app
     * @return 应用信息
     */
    @Override
    public Boolean addAppInfo(SysAppDto app) {
        String clientId = IdWorker.getIdStr();
        String clientSecret = RandomValueUtils.uuid();
        app.setId(clientId);
        app.setAppSecret(clientSecret);
        app.setCreateTime(new Date());
        app.setUpdateTime(app.getCreateTime());
        if (app.getIsPersist() == null) {
            app.setIsPersist(BaseConstants.DISABLED);
        }
        Boolean result = save(app);
        String clientInfoJson = JSONObject.toJSONString(app);
        // 功能授权
        app.setAuthorities(grantAccess(app.getId(), app.getAuthorities().split(",")));
        // 保持客户端信息
        ResultBody<Boolean> resp = clientDetailsRemoteServiceClient.addClient(clientId, clientSecret, BaseConstants.DEFAULT_OAUTH2_GRANT_TYPES, "", app.getRedirectUrls(), app.getScopes(), app.getResourceIds(), app.getAuthorities(), clientInfoJson);
        if (!resp.isOk()) {
            // 回滚事物
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return result && resp.isOk();
    }

    /**
     * 修改应用
     *
     * @param app 应用
     * @return 应用信息
     */
    @Override
    public Boolean updateInfo(SysAppDto app) {
        SystemApp appInfo = getById(app.getId());
        if (appInfo == null) {
            throw new OpenMessageException(app.getId() + "应用不存在!");
        }
        BeanUtils.copyProperties(app, appInfo);
        appInfo.setUpdateTime(new Date());
        Boolean result = saveOrUpdate(appInfo);
        String clientInfoJson = JSONObject.toJSONString(appInfo);
        // 功能授权
        app.setAuthorities(grantAccess(app.getId(), app.getAuthorities().split(",")));
        // 修改客户端信息
        ResultBody<Boolean> resp = clientDetailsRemoteServiceClient.updateClient(app.getId(), app.getGrantTypes(), "", app.getRedirectUrls(), app.getScopes(), app.getResourceIds(), app.getAuthorities(), clientInfoJson);
        if (!resp.isOk()) {
            // 手动事物回滚
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return result && resp.isOk();
    }

    /**
     * 重置秘钥
     *
     * @param appId
     * @return
     */
    @Override
    public String restSecret(String appId) {
        SystemApp appInfo = getById(appId);
        if (appInfo == null) {
            throw new OpenMessageException(appId + "应用不存在!");
        }
        // 生成新的密钥
        String clientSecret = RandomValueUtils.uuid();
        appInfo.setAppSecret(clientSecret);
        appInfo.setUpdateTime(new Date());
        Boolean result = saveOrUpdate(appInfo);
        ResultBody<Boolean> resp = clientDetailsRemoteServiceClient.resetSecret(appInfo.getId(), clientSecret);
        if (!resp.isOk()) {
            // 手动事物回滚
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return (result && resp.isOk()) ? clientSecret : null;
    }

    /**
     * 删除应用
     *
     * @param appId
     * @return
     */
    @Override
    public Boolean removeApp(String appId) {
        SystemApp appInfo = getById(appId);
        if (appInfo == null) {
            throw new OpenMessageException(appId + "应用不存在!");
        }
        if (appInfo.getIsPersist().equals(BaseConstants.ENABLED)) {
            throw new OpenMessageException(String.format("保留数据,不允许删除"));
        }
        Boolean result = removeById(appInfo.getId());
        // 移除授权
        grantAccessService.removeGrantAccess(BaseConstants.AUTHORITY_PREFIX_APP,appInfo.getId().toString());
        ResultBody<Boolean> resp = clientDetailsRemoteServiceClient.removeClinet(appInfo.getId());
        if (!resp.isOk()) {
            // 回滚事物
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return result && resp.isOk();
    }

    /**
     * 授权功能
     *
     * @param appId    应用ID
     * @param apiCodes api编码
     * @return authorities 授权后的权限标识
     */
    @Override
    public String grantAccess(String appId, String... apiCodes) {
        List<Long> apiIds = apiService.findIdsByCodes(apiCodes);
        return grantAccessService.addGrantAccess(appId.toString(), BaseConstants.AUTHORITY_PREFIX_APP, BaseConstants.RESOURCE_TYPE_API, apiIds.toArray(new String[apiIds.size()]));
    }

}
